﻿using Colorful.Models;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Colorful.Database;
using System;
using System.Collections.Generic;
using Microsoft.Extensions.Caching.Distributed;
using Colorful.Cache;
using Microsoft.AspNetCore.Http;
using System.Threading.Tasks;

namespace Colorful.CMS.Core
{
    /// <summary>
    /// 全局配置类
    /// </summary>
    public static class WebService
    {
        #region 相关字段
        //项目Id，用于前辍标识，如：Redis前辍
        public static string ProjectId = null;
        /// <summary>
        /// 后台路由前辍
        /// </summary>
        public static string AdminRoutePrefix = null;
        /// <summary>
        /// 网站语言
        /// </summary>
        public static List<JsonData<string>> Languages = null;
        //是否为开发环境
        public static bool IsDevelopment;
        //是否为调试模式
        public static bool IsDebug;
        /// <summary>
        /// 缓存服务
        /// </summary>
        public static CacheService CacheService;
        /// <summary>
        /// Redis
        /// </summary>
        public static RedisCache Redis;
        //public static IDistributedCache Cache;
        /// <summary>
        /// 系统设置
        /// </summary>
        public static SysSetting SysSetting;
        /// <summary>
        /// 网站设置
        /// </summary>
        public static WebSetting WebSetting;
        /// <summary>
        /// Email设置
        /// </summary>
        public static EmailSetting EmailSetting;
        /// <summary>
        /// IConfiguration
        /// </summary>
        public static IConfiguration Configuration;
        /// <summary>
        /// RazorRenderer服务
        /// </summary>
        public static RazorViewService RazorViewService;
        /// <summary>
        /// 资源路径
        /// </summary>
        public static string ResUrl;
        /// <summary>
        /// CMS API地址
        /// </summary>
        public static string CMSAPIUrl;
        /// <summary>
        /// NodeJs API地址
        /// </summary>
        public static string NodeJsAPIUrl;
        /// <summary>
        /// 后台View替换字典，如："Home/Index", "Index1"
        /// </summary>
        public static Dictionary<string, string> AdminViews = new Dictionary<string, string>();
        /// <summary>
        /// 后台View初始化回调
        /// </summary>
        public static Dictionary<string, Action<Microsoft.AspNetCore.Mvc.Controller>> AdminViewCallbacks = new Dictionary<string, Action<Microsoft.AspNetCore.Mvc.Controller>>();
        #endregion

        #region 发送验证码
        /// <summary>
        /// 发送验证码
        /// </summary>
        /// <param name="target">手机号/Email</param>
        /// <param name="expireTime">验证类型</param>
        /// <param name="expireTime">过期时间</param>
        /// <param name="maxLength">验证码位数</param>
        public static JsonResult SendCaptcha(string target, int type, TimeSpan expireTime, int maxLength = 4)
        {
            var context = System.Web.HttpContext.Current;
            var isMobile = FormHelper.IsMobile(target);
            if (string.IsNullOrEmpty(target))
                return new JsonResult() { succ = false, data = context.GetLang($"{(isMobile ? "手机号" : "Email")}不能为空！", $"{(isMobile ? "Mobile" : "Email")} can not be empty!") };
            const string sessionKey = "SendCaptchaExpire";
            var sendExpire = context.Session.Get<string>(sessionKey);
            var lastSend = string.IsNullOrEmpty(sendExpire) ? DateTime.MinValue : new DateTime(long.Parse(sendExpire));
            if (DateTime.Now < lastSend)
            {
                var seconds = Convert.ToInt32((DateTime.Now - lastSend).TotalSeconds);
                return new JsonResult() { succ = false, data = context.GetLang($"{seconds}秒后可重新发送！", $"{seconds} seconds can be re-sent!") };
            }
            using (var db = CMSDbHelper.GetDb())
            {
                var verification = db.Verifications.FirstOrDefault(a => a.TargetId == target && a.Type == type);
                if (verification == null)
                {
                    verification = new Verification()
                    {
                        TargetId = target,
                        Type = type
                    };
                }
                verification.Code = CommonHelper.GetNumberStr(4);
                verification.Expire = DateTime.Now.Add(expireTime);
                verification.LastModify = DateTime.Now;
                db.Verifications.Save(verification);
                context.Session.Set<string>(sessionKey, DateTime.Now.AddSeconds(60).Ticks.ToString());
                return new JsonResult() { succ = true, data = verification.Code };
            }
        }
        #endregion

        #region 获取唯一Id
        /// <summary>
        /// 获取唯一Id
        /// </summary>
        /// <returns></returns>
        public static string GetUniqueId()
        {
            return MongoDB.Bson.ObjectId.GenerateNewId().ToString();
        }
        #endregion

        #region 调用CMS API接口
        /// <summary>
        /// 调用CMS API接口
        /// </summary>
        /// <param name="url">API地址</param>
        /// <param name="data">提交的数据如：name=小明&sex=男</param>
        /// <returns></returns>
        public static string GetAPIUrl(string url, string data = null)
        {
            var nonce = GetUniqueId();
            var timestamp = DateTime.Now.Ticks.ToString();
            var signature = SecurityHelper.GetSignature(WebSetting.AppSecret, $"appkey={WebSetting.AppKey}", nonce, timestamp);
            url = $"{CMSAPIUrl}api/cms/{url}?appkey={WebSetting.AppKey}&nonce={nonce}&timestamp={timestamp}&signature={signature}";
            if (!string.IsNullOrEmpty(data))
                url += $"&{data}";
            return url;
        }
        #endregion

        #region 获取IP所在地
        public static async Task<string> GetLocation(string ip)
        {
            try
            {
                string place;
                if (string.IsNullOrEmpty(WebSetting.AppKey) || string.IsNullOrEmpty(WebSetting.AppSecret))
                {
                    place = null;
                }
                else
                {
                    place = await HttpHelper.GetContent(GetAPIUrl("ip", $"ip={ip}"));
                }
                string addr;
                if (!string.IsNullOrEmpty(place))
                {
                    var ipRegion = JsonHelper.Parse<IPRegion>(place);
                    if (string.IsNullOrEmpty(ipRegion.Country) || ipRegion.Country == "内网IP" || ipRegion.Province == "其他" || string.IsNullOrEmpty(ipRegion.Province))
                        addr = "本地";
                    else
                        addr = $"{ipRegion.Country} - {ipRegion.Province}";
                }
                else
                {
                    addr = "本地";
                }
                return addr;
            }
            catch (Exception ex)
            {
                System.Web.HttpContext.Current.WriteError(ex);
                return "本地";
            }
        }
        #endregion

        #region 记录日志
        public static void WriteErrorLog(Exception ex, HttpContext context = null)
        {
            if (context == null)
                context = System.Web.HttpContext.Current;
            context.WriteError(ex);

            if (WebSetting.EnableErrorLog && !(ex is InvalidException))
            {
                var errLog = new ErrorLog()
                {
                    Page = context.Request.Path,
                    PageQuery = context.Request.QueryString.HasValue ? context.Request.QueryString.Value : "",
                    HttpMethod = context.Request.Method,
                    Error = $"ERROR：{ex.Message}\r\nStack：{ex.StackTrace}",
                    IP = context.GetIP()
                };
                using (var db = CMSDbHelper.GetDb())
                {
                    db.ErrorLogs.Add(errLog);
                }
            }
        }
        #endregion

        #region SetUA 记录用户UA信息
        public static void SetUA(Microsoft.AspNetCore.Http.HttpContext context = null)
        {
            if (!WebSetting.EnableSiteStatistic) return;
            if (context == null)
                context = System.Web.HttpContext.Current;
            var ip = context.GetIP();
            var trackingId = context.GetTrackingId();
            var ua = new UserAgent()
            {
                TrackingId = trackingId,
                IP = ip,
                HttpMethod = context.Request.Method,
                Flag = context.User.GetFlag(),
                Lang = context.GetLang(),
                LoginId = context.User.GetId(),
                Page = context.Request.Path,
                PageQuery = context.Request.QueryString.Value,
                Source = context.Request.Headers["Referer"],
                UA = context.Request.Headers["HTTP_USER_AGENT"],
                AddDate = DateTime.Now
            };
            using (var db = CMSDbHelper.GetDb())
                db.UserAgents.Add(ua);
        }
        #endregion
    }
}
